package org.zachary.agent.domain.aggregate_model.user;


import jakarta.persistence.*;
import lombok.Getter;
import org.springframework.data.domain.AbstractAggregateRoot;
import org.zachary.agent.domain.aggregate_model.user.event.UserLoggedEvent;
import org.zachary.agent.domain.aggregate_model.user.event.UserRegisteredEvent;
import org.zachary.agent.domain.exception.AuthException;
import org.zachary.agent.domain.exception.UpdateUserInfoException;
import org.zachary.agent.infrastructure.converter.PasswordConverter;

import javax.naming.AuthenticationException;
import java.io.Serial;
import java.io.Serializable;
import java.time.Instant;

@Entity
@Table(name="user")
public class User extends AbstractAggregateRoot<User> implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;

    @Id
    @Getter
    private int id;
    @Getter
    private String uuid;
    @Convert(converter = PasswordConverter.class)
    private EncryptedPassword password;
    @Embedded
    private NickName nickName;
    @Embedded
    private Username username;
    private ProfilePicture profilePicture;
    private ContactUs contactUs;
    private Gender gender;
    private Address address;
    @Getter
    private Instant createTime;
    @Getter
    private Instant updateTime;
    @Getter
    private boolean updated;


    public User(int id,String uuid, String name, String plainPassword) {
        this.id=id;
        this.uuid = uuid;
        this.username = new Username(name);
        this.password = EncryptedPassword.fromPlaintext(plainPassword);
    }
    private User(String username,
                 String nickname,
                 String profilePicture,
                 String email,
                 String phone,
                 String gender,
                 String province,
                 String city,
                 String county,
                 String township){
        this.username = new Username(username);
        this.nickName = new NickName(nickname);
        this.profilePicture = new ProfilePicture(profilePicture);
        this.contactUs = new ContactUs(email, phone);
        this.gender = new Gender(gender);
        this.address = new Address(province, city, county, township);
        this.updateTime = Instant.now();

    }
    public static User create(String username,
                              String nickname,
                              String profilePicture,
                              String email,
                              String phone,
                              String gender,
                              String province,
                              String city,
                              String county,
                              String township){
        return new User(username,nickname,profilePicture,email,phone,gender,province,city,county,township);

    }

    protected User() {

    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", uuid='" + uuid + '\'' +
                ", password=" + password +
                ", nickName=" + nickName +
                ", username=" + username +
                ", profilePicture=" + profilePicture +
                ", contactUs=" + contactUs +
                ", gender=" + gender +
                ", address=" + address +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                ", updated=" + updated +
                '}';
    }

    public void register() {
        validateRegistration();
        registerEvent(new UserRegisteredEvent(this, this.username.getValue()));
    }

    public void login(String inputPassword) throws AuthenticationException {
        if (password.doNotMatch(inputPassword)) {
            throw new AuthException("密码错误");
        }
        registerEvent(new UserLoggedEvent(this.uuid));
    }

    public void improveInfo(){
        if(nickName==null|| contactUs==null || gender==null || address==null){
            throw new UpdateUserInfoException("缺少必要信息");
        }
        this.updated=true;
        registerEvent(this);
    }

    public void changePassword(String oldPassword, String newPassword) {
        if (password.doNotMatch(oldPassword)) {
            throw new AuthException("旧密码验证失败");
        }
        this.password = EncryptedPassword.fromPlaintext(newPassword);
    }

    private void validateRegistration() {
        if (username == null || password == null) {
            throw new AuthException("用户名和密码不可为空");
        }
    }

    public String getUsername() { return username.getValue(); }
    public String getNickName() { return nickName==null?"未设置":nickName.getValue(); }
    public String getProfilePicture() { return profilePicture==null?"未设置":profilePicture.getValue(); }
    public String getAddress() {    return address==null?"未设置":address.toString();  }
    public String getGender() { return gender==null?"未设置":gender.getValue(); }
    public String getContactUs() { return contactUs==null?"未设置":contactUs.toString(); }
    public String getPhone(){
        return contactUs==null?"未设置":contactUs.getPhone();
    }
    public String getEmail(){
        return contactUs==null?"未设置":contactUs.getEmail();
    }
    public String getProvince(){
        return address==null?"未设置":address.getProvince();
    }
    public String getCity(){
        return address==null?"未设置":address.getCity();
    }
    public String getCounty(){
        return address==null?"未设置":address.getCounty();
    }
    public String getTownship(){
        return address==null?"未设置":address.getTownship();
    }
}